package se.webbzon.boltzmann.minigame.sandbox;

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.font.HorizontalAlignment;
import se.webbzon.oschi01.font.VerticalAlignment;
import se.webbzon.oschi01.resourceset.ResourceIterator;
import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.textureset.Texture3D;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;
import se.webbzon.oschi01.worldobject.WorldObject;

public class DefaultSandBoxContainer implements SandBoxContainer {
	
	// The 2-dimensional depth of this world object.
	private static final int depth = 100;
	
	// The root class of the container content
	private final Class<? extends SandBoxItem> root;
	
	// The container instance
	private final WorldObject container;
	
	// The content of this container
	private final List<SandBoxItem> content;
	
	// The icon of the content of the container
	private SandBoxIcon icon;
	
	// The image of this container
	private ResourceIterator<?> it;
	
	// The font used to print the quantity
	private Font font;
	
	// The position of this world object
	private double x,y;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public DefaultSandBoxContainer() {
		this(null,SandBoxItem.class);
	}
	
	public DefaultSandBoxContainer(Class<? extends SandBoxItem> root) {
		this(null,root);
	}
	
	public DefaultSandBoxContainer(ResourceSet<?> pictureSet) {
		this(pictureSet,SandBoxItem.class);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public DefaultSandBoxContainer(ResourceSet<?> pictureSet, Class<? extends SandBoxItem> root) {
		if (pictureSet == null)
			pictureSet = Resources.getImageSet("minigame_sandbox_container");
		Object o = pictureSet.get(0);
		if (!(o instanceof Image) && !(o instanceof Texture3D)) 
			pictureSet = Resources.getImageSet("minigame_sandbox_container");
			
		it = new ResourceIterator(pictureSet);
		it.setSpeed(1);
		this.root = root;
		container = new WorldContainer();
		content = new ArrayList<SandBoxItem>();
		font = Resources.getFont("liberation_mono_plain").deriveFont(12f);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Clears the contents of this sand box container. **/
	public void clearContents() {
		content.clear();
		icon = null;
	}
	
	/** Removes the given sand box item from this sand box container. **/
	public boolean removeContent(SandBoxItem item) {
		if (content.remove(item)) {
			if (content.isEmpty())
				icon = null;
			return true;
		} else
			return false;
	}
	
	/** Returns a collection of all the content in this container. **/
	public Collection<SandBoxItem> getContent() {
		return Collections.unmodifiableCollection(content);
	}

	@Override public boolean draggable() {
		return false;
	}

	@Override public boolean droppable() {
		return false;
	}
	
	@Override public void setPosition(double x, double y) {
		this.x = x;
		this.y = y;
	}

	@Override public double getX() {
		return x;
	}

	@Override public double getY() {
		return y;
	}

	@Override public double getWidth() {
		return 48;
	}

	@Override public double getHeight() {
		return 48;
	}

	@Override public boolean isEmpty() {
		return content.isEmpty();
	}
	
	@Override public SandBoxIcon createIcon() {
		return null;
	}	

	@Override public int getQuantity() {
		return content.size();
	}

	@Override public boolean hasItem(SandBoxItem item) {
		return content.contains(item);
	}

	@Override public SandBoxItem pickItem(SandBox box) {
		if (content.isEmpty())
			return null;
		else {
			int size = content.size();
			SandBoxItem item;
			if (size == 1) {
				item = content.remove(0);
				icon = null;
			} else {
				item = content.remove(size-1);
			}
			box.addItem(item);
			return item;
		}
	}

	@Override public boolean putItem(SandBox box, SandBoxItem item) {
		if (!root.isInstance(item))
			return false;
		else if (content.isEmpty() || item.getClass() == content.get(0).getClass()) {
			content.add(item);
			icon = item.createIcon();
			box.removeItem(item);
			return true;
		} else
			return false;
	}

	@Override public void onAttach(SandBox box) {
		box.getWorld().createInstance(container);
	}

	@Override public void onDetach(SandBox box) {
		box.getWorld().destroyInstance(container);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** The world object container. **/
	private final class WorldContainer extends WorldObject {

		public WorldContainer() {
			super(WorldObject.onStepEnd + WorldObject.onPostDraw, depth);
		}
		
		@Override public void onStepEnd(WorldArea world) {
			it.next();
		}
		
		@Override public void onPostDraw(WorldArea world, WorldCameraPane hud) {
			int x = (int) getX();
			int y = (int) getY();
			int w = (int) getWidth();
			int h = (int) getHeight();
			int wh = w/2;
			int hh = h/2;
			Object current = it.current();
			Image img;
			if (current instanceof Image)
				img = (Image) current;
			else
				img = ((Texture3D) current).getImage();
			hud.drawImage(img, x - wh, y - hh);
			SandBoxIcon icon = DefaultSandBoxContainer.this.icon;
			if (icon != null) {
				icon.drawIcon(hud, x, y, w, h);
				int n = content.size();
				if (n > 1) {
					hud.setColor(Color.BLACK);
					hud.setHAlignment(HorizontalAlignment.RIGHT);
					hud.setVAlignment(VerticalAlignment.BOTTOM);
					hud.setFont(font);
					hud.drawString("" + n, x + wh - 3, y + hh - 3);
				}
			}
		}
		
	}

}
